package com.company.jobhandler;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.xxl.job.core.context.XxlJobHelper;
import com.xxl.job.core.handler.annotation.XxlJob;
import okhttp3.*;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.io.File;
import java.io.IOException;
import java.util.concurrent.TimeUnit;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * 增强版HTTP处理器
 * 支持多种请求类型和文件下载功能
 *
 * @author xxx
 * @version 2.0
 */
@Component
public class HttpJobHandler {

    /**
     * 任务类型常量
     */
    private static final String JOB_TYPE_HTTP = "http";
    private static final String JOB_TYPE_DOWNLOAD = "download";

    /**
     * HTTP方法常量
     */
    private static final String HTTP_GET = "GET";
    private static final String HTTP_POST = "POST";
    private static final String HTTP_PUT = "PUT";
    private static final String HTTP_DELETE = "DELETE";
    private static final String HTTP_PATCH = "PATCH";

    /**
     * 内容类型常量
     */
    private static final String CONTENT_TYPE_JSON = "application/json";
    private static final String CONTENT_TYPE_FORM = "application/x-www-form-urlencoded";
    private static final String CONTENT_TYPE_MULTIPART = "multipart/form-data";
    private static final String CONTENT_TYPE_TEXT = "text/plain";
    private static final String CONTENT_TYPE_XML = "application/xml";

    /**
     * 标准客户端，用于普通HTTP请求
     */
    private final OkHttpClient standardClient = new OkHttpClient.Builder().connectTimeout(30, TimeUnit.SECONDS).readTimeout(60, TimeUnit.SECONDS).writeTimeout(60, TimeUnit.SECONDS).build();

    /**
     * 下载客户端，用于文件下载，超时时间更长
     */
    private final OkHttpClient downloadClient = new OkHttpClient.Builder().connectTimeout(30, TimeUnit.SECONDS).readTimeout(300, TimeUnit.SECONDS).writeTimeout(300, TimeUnit.SECONDS).build();

    /**
     * 主执行方法，处理所有HTTP请求和文件下载
     */
    @XxlJob("httpJobHandler")
    public void execute() throws Exception {
        String param = XxlJobHelper.getJobParam();
        XxlJobHelper.log("开始执行HTTP请求，参数：{}", param);

        try {
            // 解析参数
            JSONObject paramObj = JSON.parseObject(param);
            validateRequiredParams(paramObj);

            String url = paramObj.getString("url");
            String method = getOrDefault(paramObj.getString("method"), HTTP_GET);
            JSONObject headers = paramObj.getJSONObject("headers");
            String jobType = getOrDefault(paramObj.getString("jobType"), JOB_TYPE_HTTP);

            // 根据任务类型执行不同操作
            if (JOB_TYPE_DOWNLOAD.equalsIgnoreCase(jobType)) {
                executeDownload(url, method, headers, paramObj);
            } else {
                // 处理HTTP请求
                handleHttpRequest(url, method, headers, paramObj);
            }
        } catch (Exception e) {
            XxlJobHelper.log("执行异常: {}", e.getMessage());
            XxlJobHelper.handleFail("执行异常: " + e.getMessage());
        }
    }

    /**
     * 验证必要参数
     */
    private void validateRequiredParams(JSONObject paramObj) {
        if (paramObj == null) {
            throw new IllegalArgumentException("参数不能为空");
        }

        String url = paramObj.getString("url");
        if (StringUtils.isEmpty(url)) {
            throw new IllegalArgumentException("URL不能为空");
        }

        // 如果是下载任务，验证保存路径
        if (JOB_TYPE_DOWNLOAD.equalsIgnoreCase(paramObj.getString("jobType"))) {
            String savePath = paramObj.getString("savePath");
            if (StringUtils.isEmpty(savePath)) {
                throw new IllegalArgumentException("下载任务的保存路径不能为空");
            }
        }
    }

    /**
     * 处理HTTP请求，兼容新旧格式
     */
    private void handleHttpRequest(String url, String method, JSONObject headers, JSONObject paramObj) throws IOException {
        String contentType = paramObj.getString("contentType");

        // 兼容原有的body字符串格式和新的JSONObject格式
        Object bodyObj = paramObj.get("body");
        if (bodyObj instanceof JSONObject) {
            executeHttpWithJsonBody(url, method, headers, contentType, (JSONObject) bodyObj);
        } else {
            String body = paramObj.getString("body");
            executeHttpWithStringBody(url, method, headers, body);
        }
    }

    /**
     * 使用字符串body执行HTTP请求（兼容原有逻辑）
     */
    private void executeHttpWithStringBody(String url, String method, JSONObject headers, String body) throws IOException {
        // 构建请求
        Request.Builder requestBuilder = new Request.Builder().url(url);
        addHeaders(requestBuilder, headers);

        // 根据HTTP方法设置请求体
        RequestBody requestBody = null;
        if (!StringUtils.isEmpty(body)) {
            requestBody = RequestBody.create(MediaType.parse(CONTENT_TYPE_JSON + "; charset=utf-8"), body);
        }

        buildRequest(requestBuilder, method, requestBody);
        executeStandardRequest(requestBuilder.build());
    }

    /**
     * 使用JSON对象body执行HTTP请求（新增功能）
     */
    private void executeHttpWithJsonBody(String url, String method, JSONObject headers, String contentType, JSONObject body) throws IOException {
        // 默认为JSON
        contentType = getOrDefault(contentType, CONTENT_TYPE_JSON);

        // 构建请求
        Request.Builder requestBuilder = new Request.Builder().url(url);
        addHeaders(requestBuilder, headers);

        // 根据内容类型和HTTP方法设置请求体
        RequestBody requestBody = buildRequestBody(contentType, body);
        buildRequest(requestBuilder, method, requestBody);

        // 执行请求
        Request request = requestBuilder.build();
        XxlJobHelper.log("发送请求: {} {}, 内容类型: {}", method, url, contentType);
        executeStandardRequest(request);
    }

    /**
     * 执行标准HTTP请求
     */
    private void executeStandardRequest(Request request) throws IOException {
        try (Response response = standardClient.newCall(request).execute()) {
            int statusCode = response.code();
            String responseBody = response.body() != null ? response.body().string() : "";

            logResponse(statusCode, responseBody);

            if (response.isSuccessful()) {
                XxlJobHelper.handleSuccess(responseBody);
            } else {
                XxlJobHelper.handleFail(String.format("请求失败，状态码: %d，响应: %s", statusCode, responseBody));
            }
        }
    }

    /**
     * 执行文件下载（新增功能）
     */
    private void executeDownload(String url, String method, JSONObject headers, JSONObject paramObj) throws IOException {
        String savePath = paramObj.getString("savePath");

        // 构建请求
        Request.Builder requestBuilder = new Request.Builder().url(url);
        addHeaders(requestBuilder, headers);

        // 处理请求方法和请求体
        if (HTTP_POST.equalsIgnoreCase(method)) {
            JSONObject body = paramObj.getJSONObject("body");
            if (body != null) {
                requestBuilder.post(RequestBody.create(MediaType.parse(CONTENT_TYPE_JSON), body.toJSONString()));
            } else {
                requestBuilder.post(RequestBody.create(null, new byte[0]));
            }
        } else {
            requestBuilder.get();
        }

        XxlJobHelper.log("发送下载请求: {}", url);

        // 执行下载
        downloadFile(requestBuilder.build(), savePath);
    }

    /**
     * 下载文件并保存到指定路径
     */
    private void downloadFile(Request request, String savePath) throws IOException {
        try (Response response = downloadClient.newCall(request).execute()) {
            if (!response.isSuccessful()) {
                XxlJobHelper.handleFail("下载失败，状态码: " + response.code());
                return;
            }

            // 创建保存目录
            File saveDir = new File(savePath).getParentFile();
            if (!saveDir.exists() && !saveDir.mkdirs()) {
                throw new IOException("无法创建目录: " + saveDir.getAbsolutePath());
            }

            // 保存文件
            File saveFile = new File(savePath);
            try (ResponseBody body = response.body(); InputStream input = body != null ? body.byteStream() : null; FileOutputStream output = new FileOutputStream(saveFile)) {

                if (input == null) {
                    throw new IOException("响应体为空");
                }

                byte[] buffer = new byte[4096];
                int bytesRead;
                long totalBytesRead = 0;
                long fileSize = body.contentLength();

                while ((bytesRead = input.read(buffer)) != -1) {
                    output.write(buffer, 0, bytesRead);
                    totalBytesRead += bytesRead;

                    // 记录下载进度
                    if (fileSize > 0) {
                        int progress = (int) (totalBytesRead * 100 / fileSize);
                        XxlJobHelper.log("下载进度: {}%", progress);
                    }
                }

                XxlJobHelper.log("文件下载完成，保存路径: {}, 文件大小: {} 字节", savePath, totalBytesRead);
                XxlJobHelper.handleSuccess("文件下载成功: " + savePath);
            }
        }
    }

    /**
     * 添加请求头
     */
    private void addHeaders(Request.Builder requestBuilder, JSONObject headers) {
        if (headers != null) {
            for (Map.Entry<String, Object> entry : headers.entrySet()) {
                requestBuilder.addHeader(entry.getKey(), String.valueOf(entry.getValue()));
            }
        }
    }

    /**
     * 根据HTTP方法构建请求
     */
    private void buildRequest(Request.Builder requestBuilder, String method, RequestBody requestBody) {
        switch (method.toUpperCase()) {
            case HTTP_GET:
                requestBuilder.get();
                break;
            case HTTP_POST:
                requestBuilder.post(requestBody != null ? requestBody : RequestBody.create(MediaType.parse(CONTENT_TYPE_JSON), "{}"));
                break;
            case HTTP_PUT:
                requestBuilder.put(requestBody != null ? requestBody : RequestBody.create(MediaType.parse(CONTENT_TYPE_JSON), "{}"));
                break;
            case HTTP_DELETE:
                if (requestBody != null) {
                    requestBuilder.delete(requestBody);
                } else {
                    requestBuilder.delete();
                }
                break;
            case HTTP_PATCH:
                requestBuilder.patch(requestBody != null ? requestBody : RequestBody.create(MediaType.parse(CONTENT_TYPE_JSON), "{}"));
                break;
            default:
                throw new IllegalArgumentException("不支持的HTTP方法: " + method);
        }
    }

    /**
     * 根据内容类型构建请求体（新增功能）
     */
    private RequestBody buildRequestBody(String contentType, JSONObject body) {
        if (body == null) {
            return null;
        }

        contentType = contentType.toLowerCase();

        // 1. 处理JSON
        if (contentType.contains(CONTENT_TYPE_JSON)) {
            return RequestBody.create(MediaType.parse(CONTENT_TYPE_JSON + "; charset=utf-8"), body.toJSONString());
        }

        // 2. 处理表单数据
        else if (contentType.contains(CONTENT_TYPE_FORM)) {
            FormBody.Builder formBuilder = new FormBody.Builder();
            for (Map.Entry<String, Object> entry : body.entrySet()) {
                formBuilder.add(entry.getKey(), String.valueOf(entry.getValue()));
            }
            return formBuilder.build();
        }

        // 3. 处理多部分表单数据
        else if (contentType.contains(CONTENT_TYPE_MULTIPART)) {
            return buildMultipartBody(body);
        }

        // 4. 处理纯文本
        else if (contentType.contains(CONTENT_TYPE_TEXT)) {
            return RequestBody.create(MediaType.parse(CONTENT_TYPE_TEXT + "; charset=utf-8"), body.getString("content"));
        }

        // 5. 处理XML
        else if (contentType.contains(CONTENT_TYPE_XML)) {
            return RequestBody.create(MediaType.parse(contentType + "; charset=utf-8"), body.getString("content"));
        }

        // 默认按JSON处理
        return RequestBody.create(MediaType.parse(CONTENT_TYPE_JSON + "; charset=utf-8"), body.toJSONString());
    }

    /**
     * 构建多部分表单请求体
     */
    private RequestBody buildMultipartBody(JSONObject body) {
        MultipartBody.Builder multipartBuilder = new MultipartBody.Builder().setType(MultipartBody.FORM);

        for (Map.Entry<String, Object> entry : body.entrySet()) {
            String key = entry.getKey();
            Object value = entry.getValue();

            // 处理文件上传
            if (value instanceof JSONObject && ((JSONObject) value).containsKey("filePath")) {
                JSONObject fileObj = (JSONObject) value;
                String filePath = fileObj.getString("filePath");
                String fileName = fileObj.getString("fileName");
                String fileType = fileObj.getString("fileType");

                if (StringUtils.isEmpty(fileName)) {
                    fileName = new File(filePath).getName();
                }

                if (StringUtils.isEmpty(fileType)) {
                    fileType = "application/octet-stream";
                }

                File file = new File(filePath);
                if (file.exists()) {
                    multipartBuilder.addFormDataPart(key, fileName, RequestBody.create(MediaType.parse(fileType), file));
                } else {
                    XxlJobHelper.log("警告：文件不存在: {}", filePath);
                }
            }
            // 处理普通字段
            else {
                multipartBuilder.addFormDataPart(key, String.valueOf(value));
            }
        }
        return multipartBuilder.build();
    }

    /**
     * 记录响应信息
     */
    private void logResponse(int statusCode, String responseBody) {
        XxlJobHelper.log("响应状态码: {}", statusCode);

        // 如果响应内容过长，只记录部分
        if (responseBody != null && responseBody.length() > 1000) {
            XxlJobHelper.log("响应内容(前1000字符): {}...", responseBody.substring(0, 1000));
        } else {
            XxlJobHelper.log("响应内容: {}", responseBody);
        }
    }

    /**
     * 获取参数值，如果为空则返回默认值
     */
    private String getOrDefault(String value, String defaultValue) {
        return StringUtils.isEmpty(value) ? defaultValue : value;
    }
}
